package YAVMM::GuestManager::Plugin::QMP;
use Moose::Role;

use feature qw(switch);

use TryCatch;
# use JSON;

use YAVMM::Error::Guest::Libvirt;

sub start_guest {
    my $self  = shift;
    my $guest = shift; # YAVMM::Guest

    my @cmd = $self->_guest_to_cmd($guest);
}

sub stop_guest {
    my $self  = shift;
    my $guest = shift;
}

sub kill_guest {
    my $self  = shift;
    my $guest = shift;
}

sub migrate_guest {
    my $self     = shift;
    my $guest    = shift;
    my $dst_host = shift;
}

sub get_guest_console_info {
    my $self  = shift;
    my $guest = shift;
}

# Build a kvm command line from a YAVMM::Guest
# Returns the command line as a list suitable for plugging
# into system()
sub _guest_to_cmd {
    my $self  = shift;
    my $guest = shift;

    my $kvm = 'kvm'; # get from config

    # TODO: How to get list of open ports? parse system(nestat -ln) or ??
    my $vnc_port = 5900; # + some modifier
    my $qmp_port = 4444; # + some modifier

    # NB: I'm abusing the fact that => is just a fat ,
    my @cmd = (
	$kvm,
	'-damonize',
	'-name'    => $guest->name,
	'-M'       => 'pc',
	'-cpu'     => $guest->cpu,
	'-smp'     => $guest->smp,
	'-m'       => $guest->ram,
	'-k'       => 'en-us', # TODO: language from guest config?
	'-monitor' => 'vc',
	'-qmp'     => "tcp:localhost:$qmp_port,server",
	'-vnc'     => "localhost:$vnc_port",
	);

    if ($guest->usb) {
	push @cmd, '-usb';

	foreach my $dev (@{ $guest->usbdevices }) {
	    push @cmd, '-usbdevice', $dev;
	}
    }

    ## add disks
    foreach my $drive (@{ $guest->drives }) {
	if ($drive->media eq 'floppy') {
	    push @cmd, '-fda', $drive->file;
	}
	else {
	    my @drive_opts = (
		'if='.$drive->type,
		'media='.$drive->media,
		);

	    if ($drive->file) {
		push @drive_opts, 'file='$drive->file;
	    }

	    push @cmd, '-drive', join(',', @drive_opts);
	}
    }

    ## add NICs
    foreach my $nic (@{ $guest->nics }) {
	push @cmd = ('-net', 'nic')
        my @nic_opts = (
	    'vlan='.$nic->qvlan,
	    'macaddr='.$nic->macaddr,
	    'model='.$nic->model,
	);

	if ($nic->name) {
	    push @nic_opts, 'name='.$nic->name;
	}

	push @cmd, join ',', @nic_options;

	push @cmd, '-net'

	given ($nic->mode) {
	    when ('tap') {
		@nic_options = (
		    'tap',
		    'vlan='.$nic->qvlan,
		);
		if ($nic->name) {
		    push @nic_opts, 'name='.$nic->name;
		}

		if ($nic->script) {
		    push @nic_opts, 'script='.$nic->script;
		}

		if ($nic->downscript) {
		    push @nic_opts, 'downscript='.$nic->script;
		}

		if ($nic->ifname) {
		    push @nic_opts, 'ifname='.$nic->ifname;
		}

		if (defined $nic->fd) {
		    push @nic_opts, 'fd='.$nic->fd;
		}
	    }
	    when ('vde') {
		@nic_opts = (
		    'vde',
		    'vlan='.$nic->qvlan,
		    );

		if ($nic->name) {
		    push @nic_opts, 'name='.$nic->name;
		}

		if ($nic->socket) {
		    push @nic_opts, 'socket='.$nic->socket;
		}

		if (defined $nic->vde_port) {
		    push @nic_opts, 'port='.$nic->vde_port;
		}
	    }
	    #when ('socket') {}
	    default {
		@nic_opts = ('none');
	    }
	}

	push @cmd, join ',', @nic_opts;
    }

    return @cmd;
}

1;

=head1 BUGS

=over

=item *

Only one floppy drive is allowed.

=item *

VDE: groupmode and octalmode not supported

=back
